home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C++ / Snippets / LaunchCreator 1.1 / notify.cc < prev    next >
Text File  |  1995-06-05  |  6KB  |  192 lines

  1. /*
  2.  ***********************************************************************
  3.  *
  4.  * The set of functions below let a (backgound) application post 
  5.  * synchronous or asynchronous notification messages to the user.
  6.  * Synchronous posting means that the posting function does not return until
  7.  * the notification message is displayed and the user dismisses it.
  8.  * In asynchronous mode, the posting function returns as soon as the
  9.  * message is queued into the notification queue (but not yet displayed!).
  10.  * The functions use the Notification Manager and the EventManager (via
  11.  * function sleep() defined elsewhere to relinquish the CPU control while
  12.  * sleeping).
  13.  *
  14.  * Synchronization between the Notification Manager and the present functions
  15.  * A field nmRefCon of the Notification Queue element is used for the
  16.  * synchronization: it is reset to 0 when the element is queued and set to
  17.  * 1 by a completion routine when the message has been posted.
  18.  * 
  19.  ***********************************************************************
  20.  */
  21.  
  22. /* MacHeaders Included */
  23. #include "mymenv.h"
  24. #include <string.h>
  25. #include <stdarg.h>
  26. #include <stdio.h>
  27. #include <Notification.h>
  28.  
  29.  
  30.                                 // Completion routine
  31. static pascal On_completion(NMRecPtr el)
  32. {
  33.     NMRemove(el);                        // Remove the notification request from
  34.                                         // the manager's queue
  35.     el->nmRefCon = 1;                    // Mark the notification element as posted
  36.     return 0;
  37. }
  38.  
  39.                                 // Create a new notification element
  40. static NMRecPtr new_element(const char * mesg)
  41. {
  42.                                     // Allocate space for the element and the string
  43.     NMRecPtr el = (NMRecPtr)NewPtr(sizeof(NMRec) + sizeof(Str255));
  44.     el->qLink = 0;
  45.     el->qType = nmType;
  46.     el->nmMark = 0;
  47.     el->nmIcon = nil;
  48.     el->nmSound = nil;                        // String is allocated right after the
  49.     el->nmStr = (unsigned char *)((char *)el + sizeof(NMRec));    // element
  50.     el->nmResp = NewNMProc(On_completion);
  51.     el->nmRefCon = 0;
  52.     
  53.     xstrncpy((char *)(el->nmStr),mesg,254);
  54.     CtoPstr((char *)el->nmStr);
  55.     
  56.     return el;                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         
  57. }
  58.  
  59.                                 // Wait until the given element is marked as
  60.                                 // completed (nmRefCon changes its value from 0
  61.                                 // to 1).
  62.                                 // The waiting though busy is gracious enough to let
  63.                                 // other processes running.
  64. static void wait_for_completion(NMRecPtr el)
  65. {
  66.     assert( el != 0 );
  67.     while( el->nmRefCon == 0 )
  68.         sleep(10);
  69.     assert( el->nmRefCon == 1 );
  70. }
  71.  
  72.                                 // Simply check if a request is posted
  73. static Boolean check_if_posted(const NMRecPtr el)
  74. {
  75.     return el->nmRefCon == 0 ? FALSE : TRUE;
  76. }
  77.  
  78.                                 // Dispose of the element
  79. static void dispose_element(NMRecPtr el)
  80. {
  81.     assert( el != 0 );
  82.     DisposePtr((char *)el);
  83. }
  84.  
  85. /*
  86.  *----------------------------------------------------------------------------
  87.  *                Managing the queue of pending notification requests
  88.  *                    Note the queue is just a circular list
  89.  */
  90.  
  91. #define Queue_size 5
  92. static  NMRecPtr Queue[Queue_size];
  93. static  unsigned int Queue_free_slot_no = 0;
  94. static  unsigned int Queue_no_filled_slots = 0;
  95.  
  96.                                 // Enqueue the element. return FALSE if the queue
  97.                                 // is filled up
  98. static Boolean enqueue(const NMRecPtr el)
  99. {
  100.     if( Queue_no_filled_slots >= Queue_size )
  101.       return FALSE;                            // The queue is filled up
  102.     Queue[Queue_free_slot_no] = el;
  103.     Queue_no_filled_slots++;
  104.     if( ++Queue_free_slot_no >= Queue_size )    // Adjust the pointer in a circular way
  105.       Queue_free_slot_no = 0;
  106.     return TRUE;
  107. }
  108.  
  109.                                 // Return the head elememt of the queue, or 0 if the
  110.                                 // queue is empty
  111. static NMRecPtr get_head(void)
  112. {
  113.     register int index;
  114.     if( Queue_no_filled_slots == 0 )
  115.       return (NMRecPtr)0;
  116.       
  117.     assert( Queue_free_slot_no < Queue_size );
  118.     index = Queue_free_slot_no - Queue_no_filled_slots;
  119.     if( index < 0 )
  120.       index += Queue_size;
  121.     return Queue[index];
  122. }
  123.  
  124.                                 // Remove the head of the queue
  125. static void remove_head(void)
  126. {
  127.     register NMRecPtr el;
  128.     assert( Queue_no_filled_slots > 0 && Queue_no_filled_slots <= Queue_size );
  129.     el = get_head();
  130.     dispose_element(el);
  131.     Queue_no_filled_slots--;
  132. }
  133.  
  134.                                 // Check out if some request in the queue of pending
  135.                                 // request have been posted. If so, remove them
  136.                                 // from the queue.
  137.                                 // Note that we expect requests are posted in the
  138.                                 // order they enqueued, i.e. in the FIFO order
  139. static void check_queue(void)
  140. {
  141.     register NMRecPtr el;
  142.     
  143.     while( (el=get_head()) != (NMRecPtr)0 && check_if_posted(el) )
  144.       remove_head();
  145. }
  146.  
  147. /*
  148.  *----------------------------------------------------------------------------
  149.  *                            Routing modules
  150.  */
  151.  
  152. void notify_and_wait(const char * messg,...)
  153. {
  154.       va_list args;
  155.       char buffer[300];
  156.     register NMRecPtr el;
  157.  
  158.       va_start(args,messg);            // Init 'args' to the beginning of
  159.                                     // the variable length list of args
  160.     assert(strlen(messg) < sizeof(buffer)-100);
  161.       vsprintf(buffer,messg,args);
  162.       
  163.       check_queue();
  164.       el = new_element(buffer);
  165.       assert( NMInstall(el) == noErr );
  166.       wait_for_completion(el);
  167.       dispose_element(el);
  168. }
  169.  
  170.                                     // Asynchronous notification
  171. void notify(const char * messg,...)
  172. {
  173.       va_list args;
  174.       char buffer[300];
  175.     register NMRecPtr el;
  176.  
  177.       va_start(args,messg);            // Init 'args' to the beginning of
  178.                                     // the variable length list of args
  179.     assert(strlen(messg) < sizeof(buffer)-100);
  180.       vsprintf(buffer,messg,args);
  181.       
  182.       check_queue();
  183.       el = new_element(buffer);
  184.       assert( NMInstall(el) == noErr );
  185.       while( !enqueue(el) )                    // If there are too many outstanding
  186.       {                                        // elements, wait until some are posted
  187.           wait_for_completion(get_head());
  188.           check_queue();
  189.       } 
  190. }
  191.  
  192.